/*
*    Phantom Test Driver v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/*
 * SSI_ColorContext.java
 *
 * Created on October 5, 2005, 10:32 PM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */

package ssi_colorizer;

//import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import java.awt.*;
import javax.swing.text.*;
import javax.swing.text.StyleContext;
import javax.swing.text.View;
import javax.swing.text.PlainView;
import javax.swing.event.DocumentEvent;

/**
 *
 * @author John
 */
public class SSI_ColorContext extends StyleContext implements ViewFactory {

    public static String DataTypePattern = "int|string|real|bool|void|window|regkey|bitmap|exception|file|options";
    
    /** Creates a new instance of SSI_ColorContext */
    public SSI_ColorContext() {
    }
    
    public View create(Element elem){
        //return new PlainView(elem);
        return new SSI_ColorView(elem);
    }
    
    class SSI_ColorView extends PlainView {

	SSI_ColorView(Element elem) {
	    super(elem);
	}
        
        public void paint(Graphics g, Shape a) {
            super.paint(g, a);
	}

        public void changedUpdate(DocumentEvent changes, Shape a, ViewFactory f) {
            super.changedUpdate(changes, a, f);
 
            // Make sure we redraw since something changed in the formatting 
            Container c = getContainer();
            if (c != null) c.repaint();
        } 

        protected int drawSelectedText(Graphics g, int x, int y, 
					 int p0, int p1) throws BadLocationException {
            // This function requires a Highlighter to be installed
          int iRet;
                    
          iRet = super.drawSelectedText(g, x, y, p0, p1);            
                    
          return iRet;
        }

        protected int getLineStart(int p) throws BadLocationException {
            Document doc = getDocument();
            
            String sTemp = doc.getText(0, p);
            int LineStart = sTemp.lastIndexOf("\n");
            LineStart = LineStart + 1;
            if(LineStart < 0){
                LineStart = 0;
            }

            return LineStart;
        } 

        protected int getLineEnd(int p) throws BadLocationException {
            Document doc = getDocument();
            
            int iEnd = doc.getLength() - p;
            
            String sTemp = doc.getText(p, iEnd);
            int LineEnd = sTemp.indexOf("\n");
            LineEnd = LineEnd - 1 + p;
            if(LineEnd < 0){
                LineEnd = doc.getLength();
            }

            return LineEnd;
        } 

        protected int drawUnselectedText(Graphics g, int x, int y, 
					 int p0, int p1) throws BadLocationException {
            
            Document doc = getDocument();
            Segment text = getLineBuffer();

            java.awt.Color CommentColor = new Color(60, 160, 60);
            java.awt.Color DataTypeColor = Color.BLUE;
            java.awt.Color KeywordColor = new Color(230, 0, 0);// Color.RED;
            java.awt.Color StringColor = new Color(175, 0, 175); //new Color(120, 120, 120);//Color.DARK_GRAY;
            java.awt.Color TextColor = Color.BLACK;
            
                       
            int LastEnd = 0;
            
            
            String BackSlash = "\\";
            String Exclusions = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
            //String DataTypePattern = "int|string|real|bool|void|window|regkey|bitmap|exception|file|options";
            String KeywordPattern = "include|use|function|define|dll|return|if|for|while|else|true|false|try|catch|clear|unload|package|exit";
            String QuotePattern = "\"";
            String CommentPattern = "#";
            String TotalPattern = DataTypePattern + "|" + KeywordPattern + "|" + QuotePattern + "|" + CommentPattern;
            
            String sPre;
            String sPre2;
            String sPost;
            
            int qCtr = 0;
            int LineStart;
            int i;
            int j;
            boolean bInQuotes = false;
            boolean bInComment = false;
            String sTemp;
            String sNL = "\n";
            
            sTemp = doc.getText(0, p0);
            LineStart = sTemp.lastIndexOf("\n");
            LineStart = LineStart + 1;
            if(LineStart < 0){
                LineStart = 0;
            }
            
            sTemp = doc.getText(LineStart, p0 - LineStart);
            i = 0;
            
            j = sTemp.indexOf(CommentPattern, 0);
            
            // Need to catch a comment even if there are no quotes in the line...
            if(sTemp.indexOf(QuotePattern, 0) < 0){
                if(j >= 0){
                    bInComment = true;
                }
            }
            
            // I DONT THINK THIS IS USED ANY MORE....
            /*
            while((i = sTemp.indexOf(QuotePattern, i))>=0){
                
                if((j < i) && (j >= 0)){
                    if(bInQuotes == false){
                        bInComment = true;
                    }else{
                        // This comment is in quotes, so discard, find next
                        j = sTemp.indexOf(CommentPattern, i);
                    }
                }
                
                // Increment qCtr if not a backslash and in quotes
                if((sTemp.charAt(i-1) == BackSlash.charAt(0)) && bInQuotes){
                }else{
                    if(bInComment == false){// Probably dont need this...
                        qCtr++;
                    }
                }
                
                if((qCtr % 2) > 0 && bInComment == false){
                    bInQuotes = true;
                }else{
                    bInQuotes = false;
                }
                
                i++;
            }
             **/
                        
            Matcher matcher = Pattern.compile(TotalPattern).matcher(doc.getText(p0, p1-p0));
            //Matcher matcher = Pattern.compile(TotalPattern).matcher(doc.getText(LineStart, p1-LineStart));
            while(matcher.find()){
                int sPos = matcher.start();
                int ePos = matcher.end();
                int iExcl = 0;
                
                if(bInQuotes){
                    g.setColor(StringColor);
                }else{
                    g.setColor(TextColor);
                }
                if(bInComment){
                    g.setColor(CommentColor);
                }
                
                // Draw remaining text from last find
                doc.getText(LastEnd+p0, sPos-LastEnd, text);
                x = Utilities.drawTabbedText(text, x, y, g, this, LastEnd+p0);
                
                if((sPos+p0-1) >= 0){
                    doc.getText(sPos+p0-1, 1, text);  // Get pre character
                    sPre = text.toString();
                }else{
                    sPre = "";
                }
                
                if((sPos+p0-2) >= 0){
                    doc.getText(sPos+p0-2, 1, text);  // Get pre character
                    sPre2 = text.toString();
                }else{
                    sPre2 = "";
                }
                
                if((ePos+p0+1) <= doc.getLength()){
                    doc.getText(ePos+p0  , 1, text);  // Get post character
                    sPost = text.toString();
                }else{
                    sPost = "";
                }
                
                doc.getText(sPos+p0, ePos - sPos, text);                    
                if(Exclusions.indexOf(sPre) >= 0 && sPre.length() > 0){
                    iExcl = 1;
                }
                if(Exclusions.indexOf(sPost) >= 0 && sPost.length() > 0){
                    iExcl = 1;
                }

                if(QuotePattern.indexOf(text.toString()) >= 0){
                    if((sPre.indexOf(BackSlash)==0) && ((qCtr % 2) > 0)){
                        if(sPre2.indexOf(BackSlash) == 0){
                            // Handle double backslash at end of string
                            qCtr = qCtr + 1;
                        }
                    }else{
                        qCtr = qCtr + 1;
                        // no matter what it is in quotes for this item
                    }
                }

                // Check for quotes
                if(((qCtr % 2) > 0) && (bInComment == false)){
                    bInQuotes = true;
                }else{
                    bInQuotes = false;
                }
                
                // Check for Comment
                if(CommentPattern.indexOf(text.toString()) >= 0){
                    if(bInQuotes == false){
                        bInComment = true;
                    }
                }
                
                if(iExcl > 0){
                    g.setColor(TextColor);
                }else if(DataTypePattern.indexOf(text.toString()) >= 0){
                    g.setColor(DataTypeColor);
                }else if(KeywordPattern.indexOf(text.toString()) >= 0){
                    g.setColor(KeywordColor);
                }

                if(QuotePattern.indexOf(text.toString()) >= 0){
                    g.setColor(StringColor);  // all quotes are gray
                }

                
                if(bInQuotes){
                    g.setColor(StringColor);
                }
                if(bInComment){
                    g.setColor(CommentColor);
                }

                x = Utilities.drawTabbedText(text, x, y, g, this, sPos+p0);

                LastEnd = ePos;
            }
            
            g.setColor(TextColor);
            if(bInQuotes){
               g.setColor(StringColor);
            }
            if(bInComment){
               g.setColor(CommentColor);
            }

            int s = LastEnd+p0;
            int e = p1 - s;
            doc.getText(s, e, text);
            x = Utilities.drawTabbedText(text, x, y, g, this, LastEnd+p0);

            // Check Quotes
//            matcher = Pattern.compile("\"").matcher(doc.getText(p0, p1-p0));
//            int qCtr = 0;
//            int qStart = 0;
//            int qEnd = 0;
//            while(matcher.find()){
//                int sPos = matcher.start();
//                int ePos = matcher.end();
//                if((qCtr % 2) > 0){    // Inside quotes
//                    if((sPos+p0-1) >= 0){
//                        doc.getText(sPos+p0-1, 1, text);  // Get pre character
//                        sPre = text.toString();
//                    }else{
//                        sPre = "";
//                    }
//                    if(sPre == "\\"){
//                    }else{
//                        qCtr = qCtr + 1;
//                        qEnd = sPos;
//                        doc.getText(qStart+p0, qEnd - qStart, text);
//                        x = Utilities.drawTabbedText(text, x, y, g, this, sPos+p0);
//                    }
//                    
//                }else{                 // Outside quotes
//                    qCtr = qCtr + 1;
//                    qStart = sPos;
//                }
//                doc.getText(sPos+p0, ePos - sPos, text);
//            }
            return x; // Need to return result of drawTabbedText for highlights
        }
    }
}
